package com.chixing.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chixing.controller.WebSocketProcess;
import com.chixing.entity.*;
import com.chixing.mapper.RefundMapper;
import com.chixing.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chixing.util.Result;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p >
 *
 * @author liwenjing
 * @since 2025-10-07
 */
@Service
public class RefundServiceImpl extends ServiceImpl<RefundMapper, Refund> implements IRefundService {

    @Autowired
    private IOrderDetailService orderDetailService;
    @Autowired
    private IOrderBaseService orderBaseService;
    @Autowired
    private IScheduleService scheduleService;
    @Autowired
    private SeatStatusService seatStatusService;
    @Autowired
    private ITransactionService transactionService;
    @Autowired
    private IUserCouponService userCouponService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private WebSocketProcess webSocketProcess;

    // RefundServiceImpl.java
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result handleRefund(Integer orderId, Integer userId) throws IOException {
        // 1. 查询订单详情
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        OrderDetail orderDetail = orderDetailService.getOne(queryWrapper);

        if (orderDetail == null) {
            return Result.error("订单不存在");
        }

        // 2. 检查订单状态（已退票或取消的订单不能再次退票）
        if (orderDetail.getStatues() == 2 || orderDetail.getStatues() == 3) {
            return Result.error("该订单已退票或取消，无法重复操作");
        }
        // 3. 获取订单主表信息
        OrderBase orderBase = orderBaseService.getById(orderId);
        if (orderBase == null) {
            return Result.error("订单主信息不存在");
        }
        // 4. 获取场次信息
        Schedule schedule = scheduleService.getScheduleById(orderDetail.getScheduleId());
        if (schedule == null) {
            return Result.error("场次信息不存在");
        }
        // 退款成功后处理优惠券退回逻辑
        if (orderBase.getUserCouponId() != null && orderBase.getUserCouponId() > 0) {
            UserCoupon userCoupon = userCouponService.getUserCouponById(orderBase.getUserCouponId());
            if (userCoupon != null) {
                // 验证优惠券状态是否为已使用
                if (userCoupon.getStatues() == 0) { // 0表示已使用状态
                    LocalDateTime now = LocalDateTime.now();
                    // 检查优惠券是否在有效期内
                    if (userCoupon.getEndTime() != null && userCoupon.getEndTime().isAfter(now)) {
                        // 优惠券未失效，可以退回
                        userCoupon.setStatues(1); // 2-退回可用状态
                        userCoupon.setUpdateTime(now);
                        boolean updateResult = userCouponService.updateUserCoupon(userCoupon);
                        if (!updateResult) {
                            // 记录日志：优惠券状态更新失败
                            throw new RuntimeException("优惠券状态更新失败");
                        }
                    } else {
                        // 优惠券已失效，无法退回
                        // 可以记录日志或在退款备注中说明
                    }
                }
            }
        }

        // 4. 计算退票时间与开场时间差
        LocalDateTime startTime = schedule.getStartTime();
        LocalDateTime now = LocalDateTime.now();
        Duration duration = Duration.between(now, startTime);
        long minutesDiff = duration.toMinutes();

        // 5. 验证退票时间是否满足条件
        if (minutesDiff < 30) {
            return Result.error("电影开场前30分钟内无法退票");
        }

        // 6. 计算退票金额（示例：扣除10%手续费）
        BigDecimal originalAmount = orderDetail.getMoviePrice()
                .multiply(new BigDecimal(orderDetail.getTicketCount()));
        BigDecimal deduction = BigDecimal.ZERO;
        BigDecimal actualRefund = originalAmount;

        if (minutesDiff < 180) { // 开场前3小时内
            deduction = originalAmount.multiply(new BigDecimal("0.1")); // 扣除金额
            actualRefund = originalAmount.subtract(deduction); // 实退金额
        }

        // 7. 创建退票记录
        Refund refund = new Refund();
        refund.setOrderId(orderId);
        refund.setUserId(userId);
        refund.setUserCouponId(orderBase.getUserCouponId());
        refund.setRefundTime(LocalDateTime.now());
        refund.setDeductionAmount(deduction);
        refund.setActualRefundAmount(actualRefund);
        refund.setStatues(1); // 1-退票成功
        refund.setCreateTime(LocalDateTime.now());
        refund.setUpdateTime(LocalDateTime.now());
        refund.setVersion(1);
        save(refund);
        // 8. 更新订单详情状态为"已退票"
        orderDetail.setStatues(2); // 2-退票状态
        orderDetail.setUpdateTime(LocalDateTime.now());
        orderDetailService.updateById(orderDetail);

        // 9. 更新订单主表状态为"已退票"
        if (orderBase != null) {
            orderBase.setStatues(2); // 2-退票状态
            orderBase.setUpdateTime(LocalDateTime.now());
            orderBaseService.updateById(orderBase);
        }

        // 10. 释放座位
        seatStatusService.cancelBooking(
                orderBase.getScheduleId(),
                orderBase.getSeatCoordinates()
        );

        try {
            // 更新交易流水状态
            Transaction transaction = transactionService.getTransactionByOrderId(orderId);
            if (transaction != null) {
                transaction.setStatues(2); // 2-已退款
                transaction.setUpdateTime(LocalDateTime.now());
                transactionService.updateTransaction(transaction);
            }
        } catch (Exception e) {
            throw new RuntimeException("退款失败: " + e.getMessage(), e);
        }
//        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());

        /*// 退票成功后推送消息
        Map<String, Object> messageData = new HashMap<>();
        messageData.put("userId", userId);
        messageData.put("message", "已完成退票，金额将在1小时内退回");
        messageData.put("orderId", orderId);
        messageData.put("refundAmount", actualRefund);
        messageData.put("timestamp", LocalDateTime.now());

        // 发送到消息队列
        rabbitTemplate.convertAndSend("notification_exchange", "ticket.refunded", messageData);
        String message = "已完成退票，金额将在1小时内退回";
        webSocketProcess.sendMessage(userId, message);
*/
        return Result.updateSuccess(refund);
    }
}